package com.macro.mall.service.impl;

import com.github.pagehelper.PageHelper;
import com.macro.mall.common.api.CommonResult;
import com.macro.mall.dao.*;
import com.macro.mall.dto.*;
import com.macro.mall.mapper.*;
import com.macro.mall.model.*;
import com.macro.mall.service.OmsOrderService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单管理Service实现类
 */
@Service
public class OmsOrderServiceImpl implements OmsOrderService {
    @Autowired
    private OmsOrderMapper orderMapper;
    @Autowired
    private OmsOrderDao orderDao;
    @Autowired
    private OmsOrderOperateHistoryDao orderOperateHistoryDao;
    @Autowired
    private OmsOrderOperateHistoryMapper orderOperateHistoryMapper;
    @Autowired
    private OmsOrderItemDao omsOrderItemDao;
    @Autowired
    private PmsSkuStockDao pmsSkuStockDao;
    @Autowired
    private PmsStockDao pmsStockDao;
    @Autowired
    private PmsStockMapper pmsStockMapper;
    @Autowired
    private OmsAgentSendDao omsAgentSendDao;
    @Autowired
    private PmsProductMapper productMapper;
    @Autowired
    private OmsOrderItemMapper omsOrderItemMapper;
    @Autowired
    private PmsCombinedProductMapper pmsCombinedProductMapper;
    @Autowired
    private SmsCouponHistoryMapper couponHistoryMapper;
    @Autowired
    private OmsOrderItemMapper itemMapper;
    @Autowired
    private PmsSkuStockMapper skuStockMapper;
    @Autowired
    private UmsMemberMapper umsMemberMapper;
    @Autowired
    private SmsCouponMapper couponMapper;
    @Autowired
    private OmsDistributionOrderMapper omsDistributionOrderMapper;

    @Override
    public List<OmsOrder> list(OmsOrderQueryParam queryParam, Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum, pageSize);

        return orderDao.getList(queryParam);
    }

    @Override
    public int delivery(List<OmsOrderDeliveryParam> deliveryParamList) {
        //批量发货
        List<PmsSkuStock> forSkuUpdate = new ArrayList<>();
        List<PmsStock> forStockUpdate = new ArrayList<>();
        List<OmsAgentSend> omsAgentSends = new ArrayList<>();
        for (OmsOrderDeliveryParam orderDeliveryParam:deliveryParamList) {
            Long orderId = orderDeliveryParam.getOrderId();
            Integer needAgentSend = 0;
            OmsOrderDetail orderDetail = this.orderDao.getDetail(orderId);
            List<OmsOrderItem> itemList = orderDetail.getOrderItemList().stream().filter(omsOrderItem -> OmsOrderItem.STATUS.WAIT_SEND.value() == omsOrderItem.getStatus()).collect(Collectors.toList());
            this.omsOrderItemDao.updateOrderItemStatus(itemList,OmsOrderItem.STATUS.WAIT_RECEIVE.value());
            //扣减库存
            List<PmsSkuStockParam> stockList = orderDeliveryParam.getStockList().stream().filter(e-> e.getNum() != 0).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(stockList)){
                Map<Long, List<PmsSkuStockParam>> map = stockList.stream().collect(Collectors.groupingBy(PmsSkuStockParam::getSkuStockId));
                for(Map.Entry<Long,List<PmsSkuStockParam>> entry:map.entrySet()){
                    Long stockId = entry.getKey();
                    List<PmsSkuStockParam> numList = entry.getValue();
                    Integer reduceNum = 0;
                    if(!CollectionUtils.isEmpty(numList)){
                        reduceNum = numList.stream().collect(Collectors.summingInt(PmsSkuStockParam::getNum));
                        if(reduceNum.compareTo(0)>0){
                            PmsSkuStock pmsSkuStock = new PmsSkuStock();
                            pmsSkuStock.setId(stockId);
                            pmsSkuStock.setStock(reduceNum);//注意,这里做的是库存的增量加减，不是全量
                            forSkuUpdate.add(pmsSkuStock);
                        }
                        List<PmsSkuStockParam> needAgentSendList = numList.stream().filter(pmsSkuStockParam -> pmsSkuStockParam.getAgentId() != null).collect(Collectors.toList());
                        if(!CollectionUtils.isEmpty(needAgentSendList)){
                            needAgentSend =1;
                        }
                        List<PmsStock> pmsStockList = numList.stream().map(e -> {
                            PmsStock pmsStock = new PmsStock();
                            pmsStock.setId(e.getStockId());
                            pmsStock.setStock(e.getNum());//注意,这里做的是库存的增量加减，不是全量
                            return pmsStock;
                        }).collect(Collectors.toList());
                        if(!CollectionUtils.isEmpty(pmsStockList)){
                            forStockUpdate.addAll(pmsStockList);
                            if(needAgentSend.equals(1)){//需要经纪人发货
                                List<OmsAgentSend> omsAgentSendList = numList.stream().map(e -> {
                                    OmsAgentSend omsAgentSend = new OmsAgentSend();
                                    omsAgentSend.setAgentId(e.getAgentId());
                                    omsAgentSend.setNum(e.getNum());
                                    omsAgentSend.setOrderId(orderId);
                                    omsAgentSend.setOrderItemId(e.getOrderItemId());
                                    omsAgentSend.setSkuId(e.getSkuStockId());
                                    return omsAgentSend;
                                }).collect(Collectors.toList());
                                if(!CollectionUtils.isEmpty(needAgentSendList)){
                                    omsAgentSends.addAll(omsAgentSendList);
                                }
                            }
                        }
                    }
                }

            }
            orderDeliveryParam.setAgentSend(needAgentSend);
        }
        int count = orderDao.delivery(deliveryParamList);
        //添加操作记录
        List<OmsOrderOperateHistory> operateHistoryList = deliveryParamList.stream()
                .map(omsOrderDeliveryParam -> {
                    OmsOrderOperateHistory history = new OmsOrderOperateHistory();
                    history.setOrderId(omsOrderDeliveryParam.getOrderId());
                    history.setCreateTime(new Date());
                    history.setOperateMan("后台管理员");
                    history.setOrderStatus(2);
                    history.setNote("完成发货");
                    return history;
                }).collect(Collectors.toList());
        if(forSkuUpdate.size()>0){
            this.pmsSkuStockDao.updateList(forSkuUpdate);
        }
        if(forStockUpdate.size()>0){
            //比如门店只有1件库存，发货发3个也能发，在这判断，抛异常
            String msg = "";
            for (PmsStock pmsStock : forStockUpdate){
                PmsStock pmsStockDb = pmsStockMapper.selectByPrimaryKey(pmsStock.getId());
                if (pmsStockDb.getStock() - pmsStock.getStock() < 0) {
                    if (pmsStockDb.getAgentId() != null) {
                        UmsMember member = umsMemberMapper.selectByPrimaryKey(pmsStockDb.getSkuStockId());
                        msg = "经纪人" + member.getRealName() + "的库存数量不足";
                    }else {
                        msg = "门店的库存数量不足";
                    }
                    throw new RuntimeException(msg);
                }
            }
            this.pmsStockDao.updateList(forStockUpdate);
        }
        if(omsAgentSends.size()>0){
            this.omsAgentSendDao.insertList(omsAgentSends);
        }
        if(operateHistoryList.size()>0){
            this.orderOperateHistoryDao.insertList(operateHistoryList);
        }

        return count;
    }
    @Override
    public int deliveryOne(OmsOrderDeliveryParam deliveryParam) throws RuntimeException{
        List<OmsOrderDeliveryParam> list = new ArrayList<>();
        list.add(deliveryParam);
        return this.delivery(list);
    }

    @Override
    public CommonResult<List<OmsOrderItemDTO>> deliveryData(Long orderId, Long agentId) {
        String msg = "";
        List<OmsOrderItemDTO> list = new ArrayList<>();
        OmsOrderItemExample itemExample = new OmsOrderItemExample();
        itemExample.createCriteria().andOrderIdEqualTo(orderId);
        List<OmsOrderItem> omsOrderItems = this.omsOrderItemMapper.selectByExample(itemExample);
        if(!CollectionUtils.isEmpty(omsOrderItems)){
            Map<Long, List<OmsOrderItem>> productOrderItemMap = omsOrderItems.stream().collect(Collectors.groupingBy(OmsOrderItem::getProductId));
            List<Long> productIds = omsOrderItems.stream().map(OmsOrderItem::getProductId).collect(Collectors.toList());
            PmsProductExample example = new PmsProductExample();
            example.createCriteria().andIdIn(productIds);
            Map<Long, List<PmsProduct>> productMap = this.productMapper.selectByExample(example).stream().collect(Collectors.groupingBy(PmsProduct::getId));
            for (Map.Entry<Long, List<OmsOrderItem>> entry:productOrderItemMap.entrySet()) {
                Long key = entry.getKey();
                List<OmsOrderItem> items = entry.getValue();
                if(productMap.get(key)!=null&&productMap.get(key).get(0)!=null){
                    PmsProduct pmsProduct = productMap.get(key).get(0);
                    if(pmsProduct.getType().equals(1)){
                        //处理组合商品
                        for (OmsOrderItem orderItem:items) {
                            PmsCombinedProductExample combinedProductExample = new PmsCombinedProductExample();
                            combinedProductExample.createCriteria().andParentIdEqualTo(orderItem.getProductSkuId());
                            //购买的组合商品的子商品集合
                            List<PmsCombinedProduct> pmsCombinedProducts = pmsCombinedProductMapper.selectByExample(combinedProductExample);
                            for (PmsCombinedProduct combinedProduct: pmsCombinedProducts) {
                                //每个子商品可能两条orderItemDTO一条门店的，一条经纪人的
                                OmsOrderItemDTO orderItemDTO = new OmsOrderItemDTO();
                                BeanUtils.copyProperties(orderItem,orderItemDTO);
                                List<PmsStockDTO> result = this.pmsStockDao.getOrderItemAndStockBySkuId(combinedProduct.getSkuStockId(), agentId);
                                Integer sum = result.stream().mapToInt(PmsStockDTO::getStock).sum();
                                PmsSkuStock pmsSkuStock = skuStockMapper.selectByPrimaryKey(result.get(0).getSkuStockId());
                                PmsProduct product = productMapper.selectByPrimaryKey(pmsSkuStock.getProductId());
                                if (sum <= 0 || combinedProduct.getNum() * orderItem.getProductQuantity() > sum) {
                                    msg += orderItem.getProductName() + "下需要的子商品" + product.getName() + "|规格：" + pmsSkuStock.getSpData() + "库存不足";
                                }
                                if (!CollectionUtils.isEmpty(result)) {
                                    for (PmsStockDTO dto : result) {

                                        //把商品规格信息加到orderItemDTO中
                                        orderItemDTO.setProductName(product.getName());
                                        orderItemDTO.setProductPic(pmsSkuStock.getPic());
                                        orderItemDTO.setProductQuantity(combinedProduct.getNum() * orderItem.getProductQuantity());
                                        orderItemDTO.setProductPrice(combinedProduct.getCombinedPrice());
                                        orderItemDTO.setProductSkuId(pmsSkuStock.getId());
                                        orderItemDTO.setProductAttr(pmsSkuStock.getSpData());
                                        orderItemDTO.setStockList(result);
                                    }
                                }
                                list.add(orderItemDTO);
                            }
                        }
                    }else{
                        for (OmsOrderItem orderItem:items) {
                            List<OmsOrderItemDTO> result = this.pmsStockDao.getOrderItemAndStock(orderId,orderItem.getProductSkuId(),agentId);

                            if(!CollectionUtils.isEmpty(result)){
                                list.addAll(result) ;
                            }
                        }
                    }
                }
            }

        }
        return CommonResult.success(list,msg);
    }



    @Override
    public int close(List<Long> ids, String note) {
        OmsOrder record = new OmsOrder();
        record.setStatus(4);
        OmsOrderExample example = new OmsOrderExample();
        example.createCriteria().andDeleteStatusEqualTo(0).andIdIn(ids);
        List<OmsOrder> omsOrders = orderMapper.selectByExample(example);
        for (OmsOrder omsOrder : omsOrders){
            //修改优惠券使用状态
            updateCouponStatus(omsOrder.getCouponId(), omsOrder.getMemberId(), 0,null);
            OmsOrderItemExample itemExample = new OmsOrderItemExample();
            itemExample.createCriteria().andOrderIdEqualTo(omsOrder.getId());
            List<OmsOrderItem> omsOrderItems = itemMapper.selectByExample(itemExample);
            //修改库存
            if (!CollectionUtils.isEmpty(omsOrderItems)) {
                releaseSkuStockLock(omsOrderItems);
            }
        }
        int count = orderMapper.updateByExampleSelective(record, example);
        List<OmsOrderOperateHistory> historyList = ids.stream().map(orderId -> {
            OmsOrderOperateHistory history = new OmsOrderOperateHistory();
            history.setOrderId(orderId);
            history.setCreateTime(new Date());
            history.setOperateMan("后台管理员");
            history.setOrderStatus(4);
            history.setNote("订单关闭:"+note);
            return history;
        }).collect(Collectors.toList());
        orderOperateHistoryDao.insertList(historyList);
        return count;
    }

    @Override
    public int delete(List<Long> ids) {
        OmsOrder record = new OmsOrder();
        record.setDeleteStatus(1);
        OmsOrderExample example = new OmsOrderExample();
        example.createCriteria().andDeleteStatusEqualTo(0).andIdIn(ids);
        return orderMapper.updateByExampleSelective(record, example);
    }

    @Override
    public OmsOrderDetail detail(Long id) {
        return orderDao.getDetail(id);
    }

    @Override
    public int updateReceiverInfo(OmsReceiverInfoParam receiverInfoParam) {
        OmsOrder order = new OmsOrder();
        order.setId(receiverInfoParam.getOrderId());
        order.setReceiverName(receiverInfoParam.getReceiverName());
        order.setReceiverPhone(receiverInfoParam.getReceiverPhone());
        order.setReceiverPostCode(receiverInfoParam.getReceiverPostCode());
        order.setReceiverDetailAddress(receiverInfoParam.getReceiverDetailAddress());
        order.setReceiverProvince(receiverInfoParam.getReceiverProvince());
        order.setReceiverCity(receiverInfoParam.getReceiverCity());
        order.setReceiverRegion(receiverInfoParam.getReceiverRegion());
        order.setModifyTime(new Date());
        int count = orderMapper.updateByPrimaryKeySelective(order);
        //插入操作记录
        OmsOrderOperateHistory history = new OmsOrderOperateHistory();
        history.setOrderId(receiverInfoParam.getOrderId());
        history.setCreateTime(new Date());
        history.setOperateMan("后台管理员");
        history.setOrderStatus(receiverInfoParam.getStatus());
        history.setNote("修改收货人信息");
        orderOperateHistoryMapper.insert(history);
        return count;
    }

    @Override
    public int updateMoneyInfo(OmsMoneyInfoParam moneyInfoParam) {
        OmsOrder order = new OmsOrder();
        order.setId(moneyInfoParam.getOrderId());
        order.setFreightAmount(moneyInfoParam.getFreightAmount());
        order.setDiscountAmount(moneyInfoParam.getDiscountAmount());
        order.setModifyTime(new Date());
        int count = orderMapper.updateByPrimaryKeySelective(order);
        //插入操作记录
        OmsOrderOperateHistory history = new OmsOrderOperateHistory();
        history.setOrderId(moneyInfoParam.getOrderId());
        history.setCreateTime(new Date());
        history.setOperateMan("后台管理员");
        history.setOrderStatus(moneyInfoParam.getStatus());
        history.setNote("修改费用信息");
        orderOperateHistoryMapper.insert(history);
        return count;
    }

    @Override
    public int updateNote(Long id, String note, Integer status) {
        OmsOrder order = new OmsOrder();
        order.setId(id);
        order.setNote(note);
        order.setModifyTime(new Date());
        int count = orderMapper.updateByPrimaryKeySelective(order);
        OmsOrderOperateHistory history = new OmsOrderOperateHistory();
        history.setOrderId(id);
        history.setCreateTime(new Date());
        history.setOperateMan("后台管理员");
        history.setOrderStatus(status);
        history.setNote("修改备注信息："+note);
        orderOperateHistoryMapper.insert(history);
        return count;
    }


    /**
     * 解除订单商品库存锁定
     * 区分普通商品和组合商品
     * @param orderItemList
     */
    @Override
    public void releaseSkuStockLock(List<OmsOrderItem> orderItemList){
        List<OmsOrderItem> result = new ArrayList<>();
        for(OmsOrderItem item : orderItemList){
            if (!item.getProductType().equals(1)) {
                //普通商品
                result.add(item);
            } else{
                //组合商品
                PmsCombinedProductExample example = new PmsCombinedProductExample();
                example.createCriteria().andParentIdEqualTo(item.getProductSkuId());
                //购买的组合商品的子商品集合
                List<PmsCombinedProduct> pmsCombinedProducts = pmsCombinedProductMapper.selectByExample(example);
                //子商品
                for (PmsCombinedProduct pmsCombinedProduct: pmsCombinedProducts) {
                    //每个子商品在组合商品中的数量
                    OmsOrderItem combined = new OmsOrderItem();
                    //子商品的skuId
                    combined.setProductSkuId(pmsCombinedProduct.getSkuStockId());
                    //子商品在该订单中的总数量=在组合商品中的数量*订单中的数量
                    combined.setProductQuantity(pmsCombinedProduct.getNum()*item.getProductQuantity());
                    result.add(combined);
                }
            }
        }
        pmsSkuStockDao.releaseSkuStockLock(result);
    }

    @Override
    public CommonResult giveOrderToAgent(Long orderId, Long agentId) {
        //查出该订单
        OmsOrder omsOrder = orderMapper.selectByPrimaryKey(orderId);
        if (omsOrder.getAgentId() == null) {
            //把该订单归到该经纪人下
            omsOrder.setAgentId(agentId);
            orderMapper.updateByPrimaryKeySelective(omsOrder);
            //如果订单是已完成的，给分销员加记录
            if (omsOrder.getStatus().equals(3)) {
                this.insertByOrderId(omsOrder);
            }
            return CommonResult.success("操作成功");
        }
        return CommonResult.failed("该订单已有经纪人");
    }


    /**
     * 将优惠券信息更改为指定状态
     *
     * @param couponId  优惠券id
     * @param memberId  会员id
     * @param useStatus 0->未使用；1->已使用
     */
    private void updateCouponStatus(Long couponId, Long memberId, Integer useStatus,String orderSn) {
        if (couponId == null) return;
        //查询第一张优惠券
        SmsCouponHistoryExample example = new SmsCouponHistoryExample();
        example.createCriteria().andMemberIdEqualTo(memberId)
                .andCouponIdEqualTo(couponId).andUseStatusEqualTo(useStatus == 0 ? 1 : 0);
        List<SmsCouponHistory> couponHistoryList = couponHistoryMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(couponHistoryList)) {
            SmsCouponHistory couponHistory = couponHistoryList.get(0);
            SmsCoupon smsCoupon = couponMapper.selectByPrimaryKey(couponId);
            if(useStatus.equals(1)){
                couponHistory.setUseTime(new Date());
                couponHistory.setOrderSn(orderSn);
                //使用了优惠券，把优惠券的使用数量+1
                smsCoupon.setUseCount(smsCoupon.getUseCount() + 1);
            }else{
                couponHistory.setUseTime(null);
                couponHistory.setOrderSn(null);
                //回滚了优惠券，把优惠券的使用数量-1
                smsCoupon.setUseCount(smsCoupon.getUseCount() - 1);
            }
            couponHistory.setUseStatus(useStatus);
            couponHistoryMapper.updateByPrimaryKeySelective(couponHistory);
            couponMapper.updateByPrimaryKey(smsCoupon);
        }
    }

    /**
     * 增加经纪人分销记录
     * @author 高强
     * @date 2021/1/8 11:12
     * @param omsOrder:
     * @return int
     */
    private int insertByOrderId(OmsOrder omsOrder) {
        OmsOrderItemExample example = new OmsOrderItemExample();
        example.createCriteria().andOrderIdEqualTo(omsOrder.getId()).andStatusEqualTo(3);
        if (omsOrder.getAgentId() != null) {
            List<OmsOrderItem> omsOrderItems = this.itemMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(omsOrderItems)) {
                return 0;
            }
            OmsDistributionOrder omsDistributionOrder = new OmsDistributionOrder();
            omsDistributionOrder.setCreateTime(new Date());
            omsDistributionOrder.setMemberId(omsOrder.getMemberId());
            omsDistributionOrder.setOrderId(omsOrder.getId());
            omsDistributionOrder.setOrderSn(omsOrder.getOrderSn());
            omsDistributionOrder.setStatus(OmsDistributionOrder.STATUS.FINISH.value());
            omsDistributionOrder.setStoreId(omsOrder.getUserStoreId());
            omsDistributionOrder.setStoreUserId(omsOrder.getUserId());
            //跟经纪人绑定
            omsDistributionOrder.setAgentId(omsOrder.getAgentId());
            BigDecimal commissionAmount = BigDecimal.ZERO;
            for (OmsOrderItem e : omsOrderItems) {
                PmsProduct product = productMapper.selectByPrimaryKey(e.getProductId());
                BigDecimal multiply = new BigDecimal(e.getProductQuantity()).multiply(product.getCommission())
                        .multiply(e.getProductPrice().subtract(e.getPromotionAmount()).subtract(e.getCouponAmount()))
                        .divide(BigDecimal.TEN.multiply(BigDecimal.TEN), 2);
                e.setCommissionAmount(multiply);
                itemMapper.updateByPrimaryKey(e);
                commissionAmount = commissionAmount.add(e.getCommissionAmount());
            }
            if (commissionAmount.compareTo(BigDecimal.ZERO) == 0) {
                return 0;
            }
            omsDistributionOrder.setCommissionAmount(commissionAmount);
            this.omsDistributionOrderMapper.insert(omsDistributionOrder);
        }
        return 0;
    }
}
